package com.bball.court.controller.google;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.CountDownLatch;

import android.test.InstrumentationTestCase;
import android.util.Log;

import com.bball.court.R;
import com.bball.court.http.AddCourtRequestCallbacks;
import com.bball.court.http.DeleteCourtRequestCallbacks;
import com.bball.court.http.GetCourtsRequestCallbacks;
import com.bball.court.model.Court;
import com.bball.court.model.CourtList;
import com.bball.court.model.google.GoogleCourtInstanceCreator;
import com.bball.court.model.play.PlayCourtList;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;

public class GoogleCourtControllerTest extends InstrumentationTestCase {

    private GoogleCourtController4Test courtController;
    private CountDownLatch signal;
    private double latitude = 45.499384;
    private double longitude = -73.56028;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        courtController = new GoogleCourtController4Test(getInstrumentation().getTargetContext());
    }

    public void testInsertAllCourts() throws UnsupportedEncodingException, InterruptedException {
        InputStream inputStream = getInstrumentation().getTargetContext().getResources().openRawResource(R.raw.courts);
        JsonReader reader = new JsonReader(new InputStreamReader(inputStream, "UTF-8"));
        PlayCourtList courts = new GsonBuilder().registerTypeAdapter(Court.class, new GoogleCourtInstanceCreator()).create()
                .fromJson(reader, PlayCourtList.class);
        signal = new CountDownLatch(courts.size());
        for (Court court : courts) {
            courtController.addSuggestedCourt(court.getName(), null, court.getLatLng(), new String[] { court.getAddress() });
        }
        signal.await();
    }

    public void testClearCourts() throws UnsupportedEncodingException, InterruptedException {
        signal = new CountDownLatch(9);
        courtController.findClosestCourt(new GetCourtsRequestCallbacks() {

            @Override
            public void onGetCourtsRequestFailed(RuntimeException runtimeException) {
                fail();
            }

            @Override
            public void onGetCourtsRequestComplete(CourtList courts) {
                for (Court court : courts) {
                    courtController.deleteCourt(court.getCourtId(), new MockCourtDeleteCallbacks(court.getCourtId()));
                }
            }
        }, latitude, longitude, 2);
        signal.await();
    }

    public void testListCourts() throws UnsupportedEncodingException, InterruptedException {
        signal = new CountDownLatch(1);
        courtController.findClosestCourt(getCourtsRequestCallbacks, latitude, longitude, 2);
        signal.await();
    }

    private GetCourtsRequestCallbacks getCourtsRequestCallbacks = new GetCourtsRequestCallbacks() {

        @Override
        public void onGetCourtsRequestFailed(RuntimeException runtimeException) {
            fail();
        }

        @Override
        public void onGetCourtsRequestComplete(CourtList courts) {
            assertEquals(9, courts.size());
            signal.countDown();
        }
    };

    private AddCourtRequestCallbacks addCourtRequestCallback = new AddCourtRequestCallbacks() {

        @Override
        public void onAddCourtSuccess(Court court) {
            Log.i(getClass().getSimpleName(), court.getName() + " added");
            signal.countDown();
        }

        @Override
        public void onAddCourtFail(RuntimeException runtimeException) {
            Log.e(getClass().getSimpleName(), runtimeException.getMessage(), runtimeException);
            fail();
        }
    };

    private class MockCourtDeleteCallbacks implements DeleteCourtRequestCallbacks {

        private String courtId;

        public MockCourtDeleteCallbacks(String courtId) {
            this.courtId = courtId;
        }

        @Override
        public void onDeleteCourtsComplete(String courtId) {
            Log.i(getClass().getSimpleName(), courtId + " deleted");
            assertEquals(this.courtId, courtId);
            signal.countDown();
        }

        @Override
        public void onDeleteCourtsFailed(RuntimeException runtimeException) {
            Log.e(getClass().getSimpleName(), runtimeException.getMessage(), runtimeException);
            fail();
        }
    }
}
